package aimozg.joglfw.pfx;

import aimozg.joglfw.GLColor;
import aimozg.joglfw.JoglApplication;

import java.util.LinkedList;
import java.util.Random;

/**
* Created by IntelliJ IDEA.
* User: aimozg
* Date: 02.01.11
* Time: 19:50
*/
public class Emmiter {
	public Emmiter color(double r, double g, double b, double a) {
		color = new GLColor(r,g,b,a);
		return this;
	}

	class Particle{
		double x;
		double y;
		double dx;
		double dy;
		double ddx;
		double ddy;
		double life;
		double size;
		GLColor color;
		Particle(){
			this.color = Emmiter.this.color;
			double angle = -Math.toRadians(rng.nextDouble()*angleSpread+angleMin);
			double speed = between(speedMin,speedMax);
			double grav = between(gravMin,gravMax);
			this.life = between(lifeMin, lifeMax);
			this.size = between(sizeMin,sizeMax);
			x = between(x0-width/2,x0+width/2);
			y = between(y0-height/2,y0+height/2);
			dx = Math.cos(angle)*speed;
			dy = Math.sin(angle)*speed;
			ddx = gdx*grav;
			ddy = gdy*grav;
		}
		void render(JoglApplication app){
			app.setColor(color);
			double xp = x-size/2.0;
			double yp = y-size/2.0;
			app.point(xp,yp);
			app.point(xp+size,yp);
			app.point(xp+size,yp+size);
			app.point(xp,yp+size);
		}

		/**
		 * true -- delete
		 * false -- keep
		 */
		boolean stepAndCheck(double time){
			x+=dx*time;
			y+=dy*time;
			dx+=ddx*time;
			dy+=ddy*time;
			life -= time;
			return (life<=0);
		}
	}
	private double between(double min, double max){
		if (min == max){
			return min;
		} else {
			return rng.nextDouble()*(max-min)+min;
		}
	}
	private Random rng = new Random();
	private LinkedList<Particle> particles = new LinkedList<Particle>();
	public double x0 = 0;
	public double y0 = 0;
	public double width = 0;
	public double height = 0;
	public boolean burst = false;
	public GLColor color = GLColor.WHITE;
	public double sizeMin = 1;
	public double sizeMax = 1;
	public double powerMin = 1;
	public double powerMax = 1;
	public double lifeMin = 1;
	public double lifeMax = 1;
	public double speedMin = 100;
	public double speedMax = 100;
	public double gravMin = 0;
	public double gravMax = 0;
	public double gdx = 0;
	public double gdy = 1;
	public double angleMin = 0;
	public double angleSpread = 360;

	public Emmiter area(double width, double height){
		this.width = width;
		this.height = height;
		return this;
	}
	public Emmiter angle(double min, double spread){
		this.angleMin = min;
		this.angleSpread = spread;
		return  this;
	}
	public Emmiter gravity(double min, double max,double gdx, double gdy){
		this.gravMax = max;
		this.gravMin = min;
		this.gdx = gdx;
		this.gdy = gdy;
		return this;
	}
	public Emmiter pos(double x0, double y0){
		this.x0 = x0;
		this.y0 = y0;
		return this;
	}
	public Emmiter burst(boolean burst){
		this.burst = burst;
		return this;
	}
	public Emmiter color(GLColor color){
		this.color = color;
		return this;
	}
	public Emmiter power(double min,double max){
		this.powerMin = min;
		this.powerMax = max;
		return this;
	}
	public Emmiter life(double min, double max){
		this.lifeMin = min;
		this.lifeMax = max;
		return this;
	}
	public Emmiter speed(double min,double max){
		this.speedMax = max;
		this.speedMin = min;
		return this;
	}
	public Emmiter size(double min,double max){
		this.sizeMin = min;
		this.sizeMax = max;
		return this;
	}

	public void render(JoglApplication app){
		app.beginQuads();
		for (Particle p : particles){
			p.render(app);
		}
		app.end();
	}
	public void step(double dt){
		LinkedList<Particle> newPs = new LinkedList<Particle>();
		for (Particle p : particles){
			if (!p.stepAndCheck(dt)){
				newPs.add(p);
			}
		}
		particles = newPs;
		// добавление новых частиц
		if (!burst){
			addParticles(dt);
		}
	}

	public void doBurst(){
		addParticles(1.0);
	}

	private void addParticles(double dt) {
			double power = between(powerMin,powerMax);
			double nps = power*dt;
			while(nps>1){
				particles.add(new Particle());
				nps-=1.0;
			}
			if (nps>rng.nextDouble()){
				particles.add(new Particle());
			}
	}
}
